package com.suxin;

import com.suxin.aop.DefaultBeanFactoryPointcutAdvisor;
import com.suxin.aop.DefaultStaticMethodMatcherPointcut;
import com.suxin.config.MyConfiguration;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Role;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;

import javax.annotation.Resource;

/**
 * @author Tang
 * @classname App
 * @description [  ]
 * @date 2021/2/4 15:47
 */
@EnableAspectJAutoProxy
@SpringBootApplication
@EnableAsync
@EnableConfigurationProperties(value = {MyConfiguration.class})
public class App implements CommandLineRunner {

    @Resource
    MyConfiguration myConfiguration;

    public static void main(String[] args) {
        AnnotationConfigServletWebServerApplicationContext applicationContext =
                (AnnotationConfigServletWebServerApplicationContext)SpringApplication.run(App.class, args);
    }

    @Async
    @Override
    public void run(String... args) throws Exception {

        System.out.println(myConfiguration);

//        testService.hello();

//        System.out.println(taskExecutor);
//        applicationContext.publishEvent(new StopEvent("1"));

//        System.out.println(Thread.currentThread().getName());
//        System.out.println("name--->" + name);
//        System.out.println("age--->" + age);
//
//        System.out.println(applicationContext.getBean(AsyncAnnotationBeanPostProcessor.class));
//        System.out.println(applicationContext.getBean(AnnotationAsyncExecutionInterceptor.class));

    }

    /**
     * 方法拦截器
     *
     * @return
     */
//    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    MethodInterceptor interceptor() {
        return new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                System.out.println("---interceptor---");
                return methodInvocation.proceed();
            }
        };
    }

    /**
     * 切入点
     *
     * @return
     */
//    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    DefaultStaticMethodMatcherPointcut pointcut() {
        return new DefaultStaticMethodMatcherPointcut();
    }

    /**
     * 切入点 + 通知
     *
     * @return
     */
//    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    DefaultBeanFactoryPointcutAdvisor advisor() {
        DefaultBeanFactoryPointcutAdvisor advisor = new DefaultBeanFactoryPointcutAdvisor(pointcut());
        advisor.setAdvice(interceptor());
        return advisor;
    }

//    @Bean
//    DefaultStaticMethodMatcherPointcutAdvisor pointcutAdvisor() {
//        DefaultStaticMethodMatcherPointcutAdvisor pointcutAdvisor = new DefaultStaticMethodMatcherPointcutAdvisor();
//        pointcutAdvisor.setAdvice(interceptor());
//        return pointcutAdvisor;
//    }



    @EventListener(classes = ContextRefreshedEvent.class)
    public void refreshedListener(ContextRefreshedEvent contextRefreshedEvent) {
        Object source = contextRefreshedEvent.getSource();
        System.out.println(source);
    }

}